package com.sxd.bill.rela;

import java.util.List;
import java.util.ArrayList;
import java.util.stream.Collectors;

import com.sxd.bill.common.enums.LabelNameEnum;
import com.sxd.bill.common.item.LabelItem;
import com.sxd.bill.common.item.Pairs;
import com.sxd.bill.common.item.TextLabelItem;
import com.sxd.bill.rela.extractor.Extractable;
import com.sxd.bill.rela.extractor.IntegrateExtractor;
import com.sxd.bill.rela.extractor.MultiAmtExtractor;
import com.sxd.bill.rela.extractor.MultiDueTimeExtractor;
import com.sxd.bill.rela.extractor.MultiSubjectExtractor;
import com.sxd.bill.rela.extractor.TemplateExtractor;
import com.sxd.bill.rela.item.RelationContextItem;
import com.sxd.bill.rela.item.CoreRelationItem;
import com.sxd.bill.rela.util.SimpleRecognizer;
import com.sxd.bill.rela.util.Spliter;

public class RelationExtractorManager {
    private List<Extractable> extractors;

    public RelationExtractorManager(ArrayList<Extractable> extractors) {
        this.extractors = extractors;
    }

    public RelationExtractorManager() {
        this.extractors = new ArrayList<>();
    }

    public void addExtractor(Extractable extractor) {
        extractors.add(extractor);
    }

    public List<Extractable> getExtractors() {
        return extractors;
    }

    public RelationContextItem extract_relation(TextLabelItem textLabelItem) {
        RelationContextItem relaContextItem = new RelationContextItem();
        // 若无标签，则返回空结果
        if (textLabelItem.getLabelItems().isEmpty()) {
            return relaContextItem;
        }
        // step1: 抽取发布者所属机构
        String publisherOrg = SimpleRecognizer.recognizePublisherOrg(textLabelItem);
        // step2: 切分发布者信息和内容信息
        Pairs<TextLabelItem, TextLabelItem> pairItem = Spliter.splitPublisherVsMessage(textLabelItem);
        // step3: 提取发布者昵称
        TextLabelItem publisherInfoItem = pairItem.getFirst();
        String nickName = publisherInfoItem.getText().trim().replaceAll(" :$", "");
        // step4: 移除消息标签中的发布者所属机构(前面已经抽取过了)
        TextLabelItem msgItem = pairItem.getSecond();
        List<LabelItem> labelItems = msgItem.getLabelItems();
        List<LabelItem> newLabelItems = labelItems.stream()
                .filter(item -> !item.getLabelName().equals(LabelNameEnum.PUB_ORG))
                .collect(Collectors.toList());
        msgItem.setLabelItems((ArrayList<LabelItem>) newLabelItems); // 更新msgItem
        // step5: 提取手机号码
        String phoneNum = SimpleRecognizer.recognizePhoneNum(textLabelItem);
        // step6: 切分消息内容并遍历每个消息段进行抽取
        List<TextLabelItem> subTextLabelItems = Spliter.splitSegments(msgItem);
        String rootTradingDirection = null;
        for (TextLabelItem item : subTextLabelItems) {
            // 识别提取总体的买卖方向
            String tmpRootTradingDirection = SimpleRecognizer.recognizeRootTradingDirection(item);
            rootTradingDirection = tmpRootTradingDirection != null ? tmpRootTradingDirection : rootTradingDirection;
            // 若无标签，则执行下一个循环
            if (item.getLabelItems().isEmpty()) {
                continue;
            }
            // 识别交易方向
            String trading = SimpleRecognizer.recognizeTradingDirection(item);
            // 遍历抽取器抽取关系实体
            for (Extractable extractor : this.extractors) {
                List<CoreRelationItem> relaItems = extractor.extract(item);
                if (!relaItems.isEmpty()) {
                    // 补充其他字段
                    String trd = trading != null ? trading : rootTradingDirection;
                    for (CoreRelationItem relaItem : relaItems) {
                        // 填充买卖方向
                        if (relaItem.getTradingDirection() == null) {
                            relaItem.setTradingDirection(trd);
                        }
                        // 填充抽取方法名称
                        relaItem.setExtractMethod(extractor.toString());
                    }
                    relaContextItem.addAllRelationItems(relaItems);
                    break;
                }
            }
        }
        relaContextItem.setPublisherOrg(publisherOrg);// 填充发布者所属机构
        relaContextItem.setPublisherNickName(nickName); // 填充发布者昵称
        relaContextItem.setPublisherPhoneNum(phoneNum); // 填充手机号码
        relaContextItem.setMessage(textLabelItem.getText());// 填充消息原文
        return relaContextItem;
    }

    public static RelationExtractorManager ofDefault() {
        RelationExtractorManager manager = new RelationExtractorManager();
        manager.addExtractor(new IntegrateExtractor());
        manager.addExtractor(new IntegrateExtractor(LabelNameEnum.ACCEPTOR));
        manager.addExtractor(new IntegrateExtractor(LabelNameEnum.DISCOUNTER));
        // manager.addExtractor(new IntegrateExtractor(LabelNameEnum.DUE_TIME));
        manager.addExtractor(MultiDueTimeExtractor.ofDefault());
        manager.addExtractor(new MultiAmtExtractor());

        TemplateExtractor templateExtractor = new TemplateExtractor();
        templateExtractor.addTemplate("(?<tradingDirection>出|收|买|卖)${票据期限1}${金额1}、${票据期限2}${金额2}\\s*${承兑人}");
        templateExtractor.addTemplate(
                "${利率1}量?(?<tradingDirection1>出|收|买|卖)${承兑人1}${票据期限1}，${利率2}量?(?<tradingDirection2>出|收|买|卖)${承兑人2}${票据期限2}");
        templateExtractor.addTemplate("(?<tradingDirection>出|收|买|卖)${票据期限1}为主的${贴现人1}贴${承兑人1}及${票据期限2}${贴现人2}贴${承兑人2}");
        templateExtractor.addTemplate(
                "(?<tradingDirection>出|收|买|卖)${票据期限}\\s*${贴现人}直?贴\\s*${承兑人1}${金额1}${利率1}\\+${承兑人2}${金额2}${利率2}");
        templateExtractor.addTemplate("(?<tradingDirection>出|收|买|卖)${票据期限}${贴现人}贴${承兑人1}，${承兑人2}${利率2}，${承兑人3}${利率3}");
        templateExtractor.addTemplate("(?<tradingDirection>出|收|买|卖)${票据期限}${贴现人1}贴${承兑人1}，${贴现人2}贴${承兑人2}");
        manager.addExtractor(templateExtractor);

        MultiSubjectExtractor multiSubjectExtractor = new MultiSubjectExtractor();
        multiSubjectExtractor.addTemplate("${票据期限}（?${承兑人}）?");
        multiSubjectExtractor.addTemplate("${票据期限}${承兑人}");
        multiSubjectExtractor.addTemplate("${票据期限}\\w{0,3}${承兑人}");
        multiSubjectExtractor.addTemplate("${票据期限}${承兑人}（${贴现人}.{0,3}）");
        multiSubjectExtractor.addTemplate("${票据期限}${利率}${承兑人}");
        multiSubjectExtractor.addTemplate("${票据期限}${承兑人}\\s*${金额}");
        multiSubjectExtractor.addTemplate("${票据期限}${承兑人}单张${金额}");
        multiSubjectExtractor.addTemplate("${票据期限}${贴现人}直?贴（?${承兑人}）?");
        multiSubjectExtractor.addTemplate("${票据期限}${贴现人}贴${承兑人}${金额}");
        multiSubjectExtractor.addTemplate("${票据期限}${贴现人}贴${承兑人}承兑票${金额}");
        multiSubjectExtractor.addTemplate("${承兑人}\\s*${金额}");
        multiSubjectExtractor.addTemplate("${承兑人}${票据期限}${金额}");
        multiSubjectExtractor.addTemplate("${贴现人}贴${承兑人}（?${金额}）?");
        multiSubjectExtractor.addTemplate("${贴现人}直?贴${承兑人}");
        multiSubjectExtractor.addTemplate("${贴现人}直?贴${承兑人}${利率}");
        multiSubjectExtractor.addTemplate("${金额}\\s*${票据期限}${承兑人}");
        multiSubjectExtractor.addTemplate("${金额}\\s*${票据期限}${贴现人}贴${承兑人}");
        multiSubjectExtractor.addTemplate("${金额}${承兑人}");
        multiSubjectExtractor.addTemplate("${金额}${承兑人}${票据期限}");
        multiSubjectExtractor.addTemplate("${利率}${承兑人}");
        multiSubjectExtractor.addTemplate("${承兑人}${利率}");
        multiSubjectExtractor.addTemplate("${承兑人}${票据期限}");
        multiSubjectExtractor.addTemplate("${票据期限}各类票");
        multiSubjectExtractor.addTemplate("${利率}(?<tradingDirection>出|收|买|卖)${承兑人}${金额}，${贴现人}贴");
        multiSubjectExtractor.addTemplate("收${票据期限}[；;]");
        multiSubjectExtractor.addTemplate("${利率}(?<tradingDirection>出|收|买|卖)${票据期限}${贴现人}贴${承兑人}${金额}");
        multiSubjectExtractor.addTemplate("${利率}量?(?<tradingDirection>出|收|买|卖)${承兑人}${票据期限}");
        multiSubjectExtractor.addTemplate("收${承兑人}、");
        multiSubjectExtractor.addTemplate("${利率}(?<tradingDirection>出|收|买|卖)${承兑人}");
        multiSubjectExtractor.addTemplate("${票据期限}.{0,2}${贴现人}");
        multiSubjectExtractor.addTemplate("${票据期限}[：]*${承兑人}");
        multiSubjectExtractor.addTemplate("${票据期限}.?${贴现人}${承兑人}");
        multiSubjectExtractor.addTemplate("${票据期限}${贴现人}${承兑人}承兑票${金额}");
        multiSubjectExtractor.addTemplate("${票据期限}${贴现人}直?贴${承兑人}${金额}${利率}");
        multiSubjectExtractor.addTemplate("${承兑人}${金额}${利率}");
        multiSubjectExtractor.addTemplate("${票据期限}${贴现人}(?:或者承兑授信)?${承兑人}"); // !!"2、捡漏收收1月.3月国贴或者承兑授信城农，财司，电商票，欢迎都清单报价",
        multiSubjectExtractor.addTemplate("${贴现人}贴${承兑人}${利率}"); // " 继续降价收1月！国贴五大132、普国133、f134，其余相应加点！额度1亿，挑授信，",
        multiSubjectExtractor.addTemplate("${票据期限}\\w{0,3}?${承兑人}${金额}");
        multiSubjectExtractor.addTemplate("${票据期限}${贴现人}贴${承兑人}（单张${金额}）"); // 2月国贴上汽财司（单张3500万元）
        multiSubjectExtractor.addTemplate("${承兑人}${贴现人}");
        multiSubjectExtractor.addTemplate("${票据期限}${承兑人}，${贴现人}贴；");
        multiSubjectExtractor.addTemplate("${票据期限}.{0,2}${贴现人}贴${承兑人}${利率}");
        multiSubjectExtractor.addTemplate("${贴现人}直?贴${票据期限}${承兑人}");
        multiSubjectExtractor.addTemplate("(?<tradingDirection>出|收|买|卖)托收${承兑人}${票据期限}${利率}");
        multiSubjectExtractor.addTemplate("${承兑人}${票据期限}${利率}");
        manager.addExtractor(multiSubjectExtractor);

        return manager;
    }
}
